package com.meixiaoliang.portal.modular.system.controller;

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.meixiaoliang.portal.core.util.AssertUtil;
import com.meixiaoliang.portal.core.util.ResponseUtil;
import com.meixiaoliang.portal.modular.system.model.Menu;
import com.meixiaoliang.portal.modular.system.model.RoleMenu;
import com.meixiaoliang.portal.modular.system.model.constant.Constant;
import com.meixiaoliang.portal.modular.system.model.enums.BooleanEnum;
import com.meixiaoliang.portal.modular.system.model.enums.DictionaryGroupEnum;
import com.meixiaoliang.portal.modular.system.model.enums.MenuTypeEnum;
import com.meixiaoliang.portal.modular.system.model.enums.RoleEnum;
import com.meixiaoliang.portal.modular.system.model.result.MenuListResult;
import com.meixiaoliang.portal.modular.system.model.vo.MenuLeftVo;
import com.meixiaoliang.portal.modular.system.service.MenuService;
import com.meixiaoliang.portal.modular.system.service.RoleMenuService;

/**
 * 菜单
 *
 * @author mei.xiaoliang@qq.com
 */
@RestController
@RequestMapping("/menu")
public class MenuController extends BaseController {

    @Autowired
    private MenuService     menuService;

    @Autowired
    private RoleMenuService roleMenuService;

    /**
     * 显示所有菜单，菜单维护使用
     */
    @RequestMapping("/listAll")
    public String listAll() {
        List<Menu> list = menuService.listAll();
        return ResponseUtil.buildSuccessResponse(list);
    }

    @RequestMapping("/listSingleAll")
    public String listSingleAll() {
        List<MenuLeftVo> list = menuService.listSingleAll();
        return ResponseUtil.buildSuccessResponse(list);
    }

    /**
     * 角色显示左侧菜单
     */
    @RequestMapping("/listLeft")
    public String listLeft() {
        MenuListResult list = menuService.listLeft(getCurrentUserId());
        return ResponseUtil.buildSuccessResponse(list);
    }

    /**
     * 显示所有菜单, 前端 ztree 拼接
     */
    //    @RequiresPermissions("system:menu")
    @PostMapping("/listForZtree")
    public String listForZtree() {
        List<Menu> list = menuService.list(null);
        for (Menu menu : list) {
            menu.setTypeValue(dictionaryService.getDictValue(DictionaryGroupEnum.MENU_TYPE, menu.getType()));
        }
        return ResponseUtil.buildSuccessResponse(list);
    }

    /**
     * 角色-菜单关系-页面
     */
    @RequiresPermissions("system:role")
    @RequestMapping("/listRole")
    public ModelAndView listRole(ModelAndView mov) {
        mov.setViewName("/system/menuRole");
        return mov;
    }

    /**
     * 显示角色-菜单关系
     */
    //    @RequiresPermissions("system:menu")
    @RequestMapping("/listByRole")
    public String listByRole(int roleId) {
        LambdaQueryWrapper<RoleMenu> queryWrapper = new QueryWrapper<RoleMenu>().lambda();
        if (RoleEnum.ADMIN.getCode() != roleId) {
            queryWrapper.eq(RoleMenu::getRoleId, roleId);
        }
        List<RoleMenu> roleMenuList = roleMenuService.list(queryWrapper);
        return ResponseUtil.buildSuccessResponse(roleMenuList);
    }

    @RequestMapping("/listType")
    public String listType() {
        ArrayList<Menu> menuList = new ArrayList<>();
        for (MenuTypeEnum e : MenuTypeEnum.values()) {
            menuList.add(new Menu().setType(e.getCode()).setTypeValue(e.getName()));
        }
        return ResponseUtil.buildSuccessResponse(menuList);
    }

    @RequestMapping("/get")
    public String get(Integer id) {
        Menu menu = menuService.getById(id);
        return ResponseUtil.buildSuccessResponse(menu);
    }

    //    @RequiresPermissions("system:menu")
    @RequestMapping("/save")
    public String save(Menu menu) {
        menu.setStatus(BooleanEnum.TRUE.getCode());
        if (null == menu.getParent()) {
            menu.setParent(Constant.ROOT_POINT);
        }
        menuService.save(menu);
        return ResponseUtil.buildSuccessResponse();
    }

    //    @RequiresPermissions("system:menu")
    @RequestMapping("/update")
    public String update(Menu menu) {
        menuService.updateById(menu);
        return ResponseUtil.buildSuccessResponse();
    }

    /**
     * 更新角色-菜单关系
     *
     * @param roleId    角色 id
     * @param selectIds 选中的菜单 id
     */
    //    @RequiresPermissions("system:role")
    @RequestMapping("/updateRoleMenu")
    public String updateRoleRule(Integer roleId, @RequestParam(defaultValue = "") int[] selectIds) {

        // 删除旧角色-菜单关系
        LambdaQueryWrapper<RoleMenu> queryWrapper = new QueryWrapper<RoleMenu>().lambda().eq(RoleMenu::getRoleId, roleId);
        roleMenuService.remove(queryWrapper);

        // 插入行角色-菜单关系
        if (selectIds.length > 0) {
            List<RoleMenu> list = new ArrayList<>(selectIds.length);
            for (Integer menuId : selectIds) {
                list.add(new RoleMenu().setRoleId(roleId).setMenuId(menuId));
            }
            roleMenuService.saveBatch(list);
        }

        return ResponseUtil.buildSuccessResponse();
    }

    /**
     * 菜单隐藏
     */
    //    @RequiresPermissions("system:menu")
    @RequestMapping("/lock")
    public String lock(Integer menuId) {
        changeStatus(menuId, BooleanEnum.FALSE);
        return ResponseUtil.buildSuccessResponse();
    }

    /**
     * 菜单显示
     */
    //    @RequiresPermissions("system:menu")
    @RequestMapping("/unlock")
    public String unlock(Integer menuId) {
        changeStatus(menuId, BooleanEnum.TRUE);
        return ResponseUtil.buildSuccessResponse();
    }

    @RequestMapping("/delete")
    public String delete(Integer id) {
        // 删除校验, 有下级，请先删除下级
        List<Menu> menuList = menuService.list(new QueryWrapper<Menu>().lambda().eq(Menu::getParent, id));
        AssertUtil.isTrue(menuList.size() == 0, "菜单存在子级，请删除子级后再操作");
        // 删除
        menuService.removeById(id);
        return ResponseUtil.buildSuccessResponse();
    }

    /**
     * 菜单状态变更
     *
     * @param menuId 菜单 id
     * @param status 状态
     */
    private void changeStatus(Integer menuId, BooleanEnum status) {
        Menu menu = new Menu().setId(menuId).setStatus(status.getCode());
        menuService.updateById(menu);
    }

}
